<script lang="ts" setup>
import type { VxeTableGridOptions } from '#/adapter/vxe-table';
import type { SystemOperateCategoriesApi } from '#/api/system/operateCategories';
import type { SystemPermissionApi } from '#/api/system/permission';
import type { SystemRoleApi } from '#/api/system/role';

import { computed, defineProps, nextTick, onMounted, ref, watch } from 'vue';

import { message } from 'ant-design-vue';

import { TableAction, useVbenVxeGrid } from '#/adapter/vxe-table';
import { getOAuth2ClientList } from '#/api/system/oauth2/client';
import { getOperateCategoriesSimpleList } from '#/api/system/operateCategories';
import { assignRoleOperate, getRoleOperateList } from '#/api/system/permission';

import { useAssignOperateFormGridColumns } from '../data';
// 选择的角色
const props = defineProps({
  role: {
    type: Object as () => SystemRoleApi.Role,
    default: null,
  },
});

const allOperationList = ref<SystemOperateCategoriesApi.OperateCategories[]>(
  [],
); // 所有业务分类数据

const checkedIds = ref<string[]>([]); // 已选中的菜单 ID 列表（含按钮 ID）
const checkedList = ref<SystemPermissionApi.RoleOperateVO[]>([]); // 已选中的业务操作权限列表
const isExpanded = ref(false); // 是否展开所有树节点

const isLinkedMode = ref(true); // 是否开启“节点关联”模式（勾选父自动勾选子）

const clientId = ref<string>(''); // 选择的应用ID
const clientOptions = ref<{ label: string; value: string }[]>([]); // 可以选择的应用列表

// 加载应用列表
async function loadClientOptions() {
  try {
    const list = await getOAuth2ClientList();
    clientOptions.value = list.map((item: any) => ({
      label: item.name,
      value: item.clientId,
    }));

    // 默认选中第一条
    if (clientOptions.value.length > 0) {
      clientId.value = clientOptions.value[0].value;
    }
  } catch {
    message.error('加载应用列表失败');
  }
}

// 页面加载时获取
onMounted(() => {
  loadClientOptions();
});

/** 工具函数：更新某个按钮 ID 是否选中 */
function updateCheckedNodeIds(
  node: SystemPermissionApi.RoleOperateVO,
  checked: boolean,
) {
  const index = checkedList.value.findIndex(
    (item) => item.nodeCode === node.nodeCode && item.type === 2,
  );
  if (checked && index === -1) {
    const operate = {
      roleId: props.role.id,
      operateCategoryId: node.operateCategoryId,
      nodeCode: node.nodeCode,
      type: 2,
    };
    checkedList.value.push(operate);
  } else if (!checked && index !== -1) {
    checkedList.value.splice(index, 1);
  }
}
function updateCheckedOperateIds(
  row: SystemOperateCategoriesApi.OperateCategories,
  checked: boolean,
) {
  const index = checkedList.value.findIndex(
    (item) => item.operateCategoryId === row.id && item.type === 1,
  );
  if (checked && index === -1) {
    const operate = {
      roleId: props.role.id,
      operateCategoryId: row.id,
      type: 1,
    };
    checkedList.value.push(operate);
  } else if (!checked && index !== -1) {
    checkedList.value.splice(index, 1);
  }
}

/** 获取某个菜单的所有子孙菜单（递归） */
function getAllDescendants(
  operateId: number,
  operationList: SystemOperateCategoriesApi.OperateCategories[],
) {
  const descendants: SystemOperateCategoriesApi.OperateCategories[] = [];

  function findChildren(id: number) {
    operationList.forEach((item) => {
      if (item.parentId === id) {
        descendants.push(item);
        findChildren(item.id);
      }
    });
  }

  findChildren(operateId);
  return descendants;
}

// 点击“展开/收起”按钮
function toggleExpand() {
  isExpanded.value = !isExpanded.value;
  if (gridApi?.grid) {
    gridApi.grid.setAllTreeExpand(isExpanded.value);
  }
}

// 设置是否为“节点关联模式”
function setLinkedMode(val: boolean) {
  isLinkedMode.value = val;
  message.info(
    `切换成功,当前模式：${isLinkedMode.value ? '节点关联' : '节点独立'}`,
  );
}

/**
 * 根据菜单 ID 列表设置已勾选的菜单行（高亮显示 + 复选框选中）
 * @param menuList 所有菜单数据
 * @param menuIds 需要勾选的菜单 ID 列表
 */
function setCheckedRowsByMenuIds(
  operationList: SystemOperateCategoriesApi.OperateCategories[],
  checkAllList: SystemPermissionApi.RoleOperateVO[],
) {
  if (gridApi?.grid) {
    gridApi.grid.clearCheckboxRow(); // 清除之前的所有勾选项
    const recordsToCheck = operationList.filter((m) =>
      checkAllList.some(
        (item) => item.operateCategoryId === m.id && item.type === 1,
      ),
    ); // 根据 ID 找出要勾选的菜单项
    gridApi.grid.setCheckboxRow(recordsToCheck, true); // 勾选对应的菜单行
  }
}

// 获取当前所有已选中的业务操作权限
function getAllCheckedList(): SystemPermissionApi.RoleOperateVO[] {
  const records = gridApi.grid?.getCheckboxRecords() || [];
  const operateIds = records.map((r) => ({
    roleId: props.role.id,
    operateCategoryId: r.id,
    type: 1,
  }));
  return [
    ...checkedList.value.filter((item) => item.type === 2),
    ...operateIds,
  ];
}

// 保存权限菜单配置
async function handleSave() {
  if (!props.role?.id) return;
  const hide = message.loading('正在保存权限...');
  try {
    await assignRoleOperate({
      roleId: props.role.id,
      list: getAllCheckedList(),
    });
    hide();
    message.success('权限保存成功');
    // 刷新
    await gridApi.reload();
  } catch {
    hide();
    message.error('保存失败');
  }
}

// 勾选/取消勾选按钮权限时触发
function onNodeCheckboxChange(
  row: SystemOperateCategoriesApi.OperateCategories,
  nodes: SystemPermissionApi.RoleOperateVO[],
  node: SystemPermissionApi.RoleOperateVO,
  checked: boolean,
) {
  updateCheckedNodeIds(node, checked);

  if (isLinkedMode.value) {
    // 如果按钮联动，则更新对应菜单行是否选中
    const allNodeCodes = nodes.map((b) => b.nodeCode);
    const anyChecked = allNodeCodes.some((nodeCode) =>
      checkedList.value.some((item) => item.nodeCode === nodeCode),
    );
    gridApi?.grid?.setCheckboxRow(row, anyChecked);
  }
}

// 初始化 vxe-grid 表格实例
const [Grid, gridApi] = useVbenVxeGrid({
  gridOptions: {
    id: 'assign-menu-table',
    columns: useAssignOperateFormGridColumns(
      checkedList,
      onNodeCheckboxChange,
      computed(() => props.role.editable), // 响应式
    ), // 表头列定义
    height: 'auto',
    proxyConfig: {
      ajax: {
        query: async () => {
          return loadRoleOperate(props.role);
        },
      },
    },
    pagerConfig: {
      enabled: false,
    },
    rowConfig: {
      keyField: 'id',
      isHover: true,
    },
    treeConfig: {
      transform: true,
      rowField: 'id',
      parentField: 'parentId',
      expandAll: false,
      accordion: false,
    },
    checkboxConfig: {
      highlight: true,
      checkMethod: () => props.role.editable,
    },
    onCheckboxChange: ({ row, checked }) => {
      updateCheckedOperateIds(row, checked);

      const nodes = row.reviewList || [];
      const descendants = getAllDescendants(row.id, allOperationList.value);

      if (isLinkedMode.value) {
        // 联动：菜单选中 → 所有子菜单、按钮也选中
        nodes.forEach((node: any) => updateCheckedNodeIds(node, checked));
        descendants.forEach((operate) => {
          updateCheckedOperateIds(operate, checked);
          const nodes = (operate as any).reviewList || [];
          nodes.forEach((node: any) => updateCheckedNodeIds(node, checked));
        });
      }
    },
    toolbarConfig: {
      refresh: true,
      search: true,
    },
  } as VxeTableGridOptions<SystemOperateCategoriesApi.OperateCategories>,
});

// 监听 role 值变化，重新加载数据
watch(
  () => props.role,
  async (role) => {
    if (!role?.id) return;
    await nextTick();
    await gridApi.reload();
  },
  { immediate: true },
);

// 监听 clientId 变化
watch(
  clientId,
  async (val) => {
    if (!props.role?.id) return;
    await nextTick();
    await gridApi.reload();
  },
  { immediate: true }, // 页面初始化也触发
);
/**
 * 加载角色业务数据
 * @param role 选择的角色
 */
async function loadRoleOperate(role: SystemRoleApi.Role) {
  if (!role?.id) return [];

  const hideLoading = message.loading({
    content: '加载权限菜单...',
    key: 'role_operation_load',
  });

  try {
    const [operateList, roleMenuIds] = await Promise.all([
      getOperateCategoriesSimpleList({ clientId: clientId.value }), // 获取所有菜单数据
      getRoleOperateList(role.id), // 获取角色已分配的菜单数据
    ]);

    allOperationList.value = operateList;
    checkedList.value = roleMenuIds;

    await nextTick();
    // 设置已勾选的菜单行
    setCheckedRowsByMenuIds(operateList, roleMenuIds);

    message.success({ content: '加载成功', key: 'role_operation_load' });

    return operateList; // 返回数据数组
  } catch {
    message.error({ content: '加载失败', key: 'role_operation_load' });
    return [];
  } finally {
    hideLoading();
  }
}
</script>

<template>
  <Grid table-title="业务/流程权限菜单">
    <template #toolbar-tools>
      <label style="margin-right: 4px">应用名称：</label>
      <a-select
        v-model:value="clientId"
        placeholder="请选择应用"
        style="width: 200px; margin-right: 12px"
        :options="clientOptions"
      />

      <TableAction
        :actions="[
          {
            label: isExpanded ? '收缩' : '展开',
            type: 'dashed',
            onClick: toggleExpand,
          },
          {
            label: '节点关联',
            type: isLinkedMode ? 'primary' : 'default',
            disabled: !props.role.editable || isLinkedMode, // 不可编辑 或 已经是节点关联模式
            onClick: () => setLinkedMode(true),
          },
          {
            label: '节点独立',
            type: !isLinkedMode ? 'primary' : 'default',
            disabled: !props.role.editable || !isLinkedMode, // 不可编辑 或 已经是节点独立模式
            onClick: () => setLinkedMode(false),
          },
          {
            label: '保存权限',
            type: 'primary',
            disabled: !props.role.editable,
            onClick: handleSave,
          },
        ]"
      />
    </template>
  </Grid>
</template>
